----------------------------------------------------------------------------------
-- Company:
-- Engineer: Kurt Metzger
--
-- Create Date: 21:55:53 11/18/2008
-- Design Name:
-- Module Name: UART_receiver - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- 0.02 - made baud rate generic .. KM 27Feb2009
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity UART_receiver is
	Generic (baud_rate: integer := 115200);
	Port ( 	rx : in STD_LOGIC;
				rts_out_n : out STD_LOGIC;
				received_byte : out STD_LOGIC_VECTOR (7 downto 0);
				req_out : out STD_LOGIC;
				ack_in : in STD_LOGIC;
				sr_in : inout STD_LOGIC_VECTOR(7 downto 0);
				clk : in STD_LOGIC;
				reset : in STD_LOGIC :='0');
end UART_receiver;

architecture Behavioral of UART_receiver is


-- baud count is (50000000/baud_rate - 1)

		signal baud_count : std_logic_vector(19 downto 0) :=
			STD_LOGIC_VECTOR(CONV_UNSIGNED((50000000/baud_rate)-1, 19));
		signal baud_counter : std_logic_vector(19 downto 0);
		signal bit_counter : std_logic_vector(3 downto 0);
		--signal sr_in : std_logic_vector(7 downto 0);
		signal rxdelay : std_logic_vector(1 downto 0);
		signal write_fifo : std_logic;
		
		type t_state is (s_idle, s_active);
		signal state : t_state := s_idle;

begin

		process(clk, rx, reset)
		begin
			if reset = '1' then
				state <= s_idle;
			elsif rising_edge(clk) then

			rxdelay <= rxdelay(0) & rx;
			baud_counter <= baud_counter-1;
			write_fifo <= '0';

		case state is
			when s_idle =>
				if rxdelay = "10" then -- look for falling edge
					baud_counter <= '0' & baud_count(baud_count'high downto 1); -- divide b
					bit_counter <= "1000";
					state <= s_active;
				end if;
	
			when s_active =>
				if baud_counter = 0 then
					baud_counter <= baud_count;
					sr_in <= rx & sr_in(7 downto 1);
					bit_counter <= bit_counter-1;
					if bit_counter = 0 then
						write_fifo <= '1';
						state <= s_idle;
					end if;
				end if;
		end case;
	end if;
end process;

	rxfifo : entity work.FIFO_16xN
	port map(
		data_in => sr_in,
		data_out => received_byte,
		read => ack_in,
		write => write_fifo,
		half_full => rts_out_n,
		data_present => req_out,
		reset => reset,
		clk => clk);	

end Behavioral;